using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Security.Cryptography;
using System.IO;

namespace Sixeyed.CacheAdapter.Helpers
{
    /// <summary>
    /// Helper class for generating GUIDs
    /// </summary>
    /// <remarks>
    /// Uses MD5 hash to ensure the same GUID is always returned from the same input
    /// </remarks>
    public static class GuidHelper
    {
        /// <summary>
        /// Returns a GUID hashed from the input
        /// </summary>
        /// <param name="inputFormat">Input string format</param>
        /// <param name="args">Input arguments</param>
        /// <returns>GUID</returns>
        public static Guid GenerateGuid(string inputFormat, params object[] args)
        {
            string input = string.Format(inputFormat, args);
            byte[] inputBytes = Encoding.Default.GetBytes(input);
            return GenerateGuid(inputBytes);
        }

        /// <summary>
        /// Returns a GUID hashed from the input
        /// </summary>
        /// <param name="inputBytes">Input byte array</param>
        /// <returns>GUID</returns>
        public static Guid GenerateGuid(byte[] inputBytes)
        {
            //use MD5 hash to get a 16-byte hash of the string:             
            MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
            byte[] hashBytes = provider.ComputeHash(inputBytes);

            //generate a guid from the hash: 
            Guid hashGuid = new Guid(hashBytes);
            return hashGuid;
        }

        /// <summary>
        /// Returns a GUID hashed from the input
        /// </summary>
        /// <param name="serializableObject">Input object</param>
        /// <returns>UID</returns>
        public static Guid GenerateGuid(object serializableObject)
        {
            string entityRepresentation = XmlSerialize(serializableObject);
            return GenerateGuid(entityRepresentation);
        }

        private static string XmlSerialize(object entity)
        {
            string serializedString = null;
            XmlSerializer fromSerializer = new XmlSerializer(entity.GetType());
            using (StringWriter writer = new StringWriter())
            {
                fromSerializer.Serialize(writer, entity);
                writer.Flush();
                serializedString = writer.ToString();
            }
            return serializedString;
        }
    }
}
